STAT 585X

Interactive graphics

Di Cook, Heike Hofmann
3/28/2014

Couple words on the lab ...

define the map, and get a clean data set for cities across the (mainland of) US

require(ggplot2)
require(grid)
require(maps)
states <- map_data("state")
map <- ggplot() + 
  geom_polygon(aes(x=long, y=lat,  group = group),
               fill="grey60", size=1, data=states,) + 
  theme_bw() + theme(axis.text=element_blank(), 
                     axis.title=element_blank(),
                     axis.line=element_blank(),
                     axis.ticks=element_blank(),
                     panel.border=element_blank(),
                     panel.grid=element_blank(),
                     aspect.ratio=1/1.5,
                     plot.margin=unit(c(-1,-1,-1,-1), units="cm"))

data(us.cities)
akhi <- which (us.cities$country.etc=="AK"| us.cities$country.etc=="HI" |
                 us.cities$country.etc=="ma")
us.cities <- us.cities[-akhi,]
us.cities$country.etc <- factor(us.cities$country.etc)
n <- nchar(us.cities$name)
us.cities$name <- substr(us.cities$name, 1, n-3)

Where should those definitions go?

  • IDK …
  • locally, the file ui.R seems to be called first
  • on the server it might be server.R

… so one suggestion would be to put this in a separate file and source it in both server.R and ui.R … not a good solution, but works

ui.R

library(shiny)
source("definitions.R")

shinyUI(pageWithSidebar(
  # Application title
  headerPanel("Finding a way"),

  # Sidebar with a slider input for number of observations
  sidebarPanel(
    selectInput("state", "State: ", choices=sort(unique(us.cities$country.etc)), selected="IA"),
    uiOutput("cities"),
    actionButton("goButton", "Add to route"),
    width=3
  ),

  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("mapPlot"),
    dataTableOutput("mytable"),
    width=9
  )
))

server.R

library(shiny)
source("definitions.R")
vals <- reactiveValues(cities=subset(us.cities, name=="Ames"))


# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {
  myCities <- reactive({
    input$goButton # set up the dependency

    isolate({
      vals$cities <- rbind(vals$cities, subset(us.cities, name==input$city & country.etc==input$state))
    })   
    vals$cities
  })

  output$cities <- renderUI({
    cities <- subset(us.cities, country.etc==input$state)
    selectInput("city", "City: ", cities$name)
  })

  output$mytable = renderDataTable({
    myCities()
  })
  output$mapPlot <- renderPlot({
    print(map + geom_point(aes(long, lat), colour="steelblue", size=3, data=myCities()) + 
            geom_path(aes(long, lat), colour="steelblue", data=myCities()))
  })

})

GUIs

  • Shiny is an example of a graphical user interface (GUI), a way for humans to interact with computers that uses widgets - windows, icons and menus - accessed by a mouse rather than a keyboard.
  • In contrast, command line interfaces (CLIs) use text entry and are solely accessible via keyboard.
  • GUIs are for new users, beginners, provide limited access to functionality, you need to make things simple
  • CLIs are full access, for advanced users.
  • “Some GUIs are good, some are bad, and some you just get used to, appreciating their good points and working around their bad ones.” Antony Unwin JSS paper
  • A successful GUI should enable the user to access the most useful commands quickly and easily and supply sensible defaults for any options that may be needed. That requires decisions on which commands are most useful, what options are sensible, and how to make the commands available.

GUIs

To be intuitive familiar widgets need to be used and mapped to appropriate data elements, that users instinctively know how to use

  • Window separates your project from other applications on the screen
  • Menus are for lists of choices, accessing categories, eg model choice
  • Sliders or scrollbars are for accessing single numerical variables
  • Buttons are for turning on or off some aspect, access logical variables
  • Check-boxes and radio buttons are for selecting categories, alternatives
  • Text boxes are for unstructured information
  • Icons to indicate actions/capabilities in reduced space

GUIs

Response needs to be fast. When a user takes an action the computer needs to respond quickly.

Designing a GUI that people find easy to use is hard. You need to know what people need to do most often and make this easy.

JMP

hexadecimal image

hexadecimal image hexadecimal image

What do new users have trouble with when using the JMP GUI?

Interactive graphics

  • gridSVG
  • iplots
  • plumbr
  • cranvas
  • anamint

gridSVG

Turn ggplot2 graphics into interactive web graphics, by exporting grid objects, and adding actions using javascript.

SVG = Scalable Vector Graphics - images defined in text format, so that they can be searched, indexed, scripted, compressed.

History

The original computer displays were vector graphics devices, eg Tektronix 4014. Graphics on the screen were defined by lines instead of bitmapped displays.

The device draws lines and curves by moving the electron beam exactly where the line is supposed to go, instead of breaking it into dots and scanning the electron beam back and forth, like a television set does. That is, to draw a line from point a to point b, it moves the electron beam to point a, turns it on, moves it directly to point b, and turns it off.

They were FAST!!!

hexadecimal image

Raster graphics

Dot matrix displays - a rectangular grid of points and associated color value.

Dominated the computer screen market since the late 1980s.

Need more pixels to have clear image.

library(png)
nasamap_png <- readPNG("../data/google-map.png")
dim(nasamap_png)
[1] 640 640   4
nasamap_png[300, 301:305, ]
       [,1]   [,2]   [,3] [,4]
[1,] 0.5333 0.6392 0.7569    1
[2,] 0.5333 0.6392 0.7569    1
[3,] 0.5333 0.6392 0.7569    1
[4,] 0.5333 0.6392 0.7569    1
[5,] 0.5333 0.6392 0.7569    1

SVG

The SVG specification has been in development since 1999, developed by the World Wide Web Consortium (W3C)

Specify graphics using drawing operations. More technical spcification, could generate very precise, geometric-defined representations.

This will draw a blue rectangle with a black outline:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" />
</svg>

Most, but not all, browsers support the format and can render the XML.

gridSVG Example

library(grid)
ggparcoord(nasa.oneloc, columns=c(7:10,13))
grobs <- grid.ls()
gnames <- grobs$name
pnames <- gnames[grep("GRID.polygon", gnames)]
for (i in unique(pnames)) { 
  grid.garnish(i,
               onmouseover=paste("frame(evt)", sep=""),
               onmouseout=paste("deframe(evt)", sep="") )
}
lnames <- gnames[grep("GRID.polyline", gnames)]
for (i in unique(lnames)) { 
  grid.garnish(i,
               onmouseover=paste("frame(evt)", sep=""),
               onmouseout=paste("deframe(evt)", sep="") )
}
grid.script(filename="http://dicook.github.io/stat585/action-2.js")
grid.export("parcoords.svg", exportCoords="inline", exportJS="inline", htmlWrapper=TRUE)

gridSVG

GRID.gTableParent.34
  background.1-5-6-1
  spacer.4-3-4-3
  panel.3-4-3-4
    grill.gTree.12
      panel.background.rect.5
      panel.grid.minor.y.polyline.7
      panel.grid.major.y.polyline.9
      panel.grid.major.x.polyline.11
    GRID.polyline.1
    panel.border.zeroGrob.2
  axis-l.3-3-3-3
    axis.line.y.zeroGrob.22
    axis
  axis-b.4-4-4-4
    axis.line.x.zeroGrob.16
    axis
  xlab.5-4-5-4
  ylab.3-2-3-2
  title.2-4-2-4

plot of chunk unnamed-chunk-3plot of chunk unnamed-chunk-3plot of chunk unnamed-chunk-3plot of chunk unnamed-chunk-3

parcoords.svg

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="798px" height="477px" viewBox="0 0 798 477" version="1.1">
....
  <script type="application/ecmascript"><![CDATA[
var gridSVGCoords = {
 "ROOT": {
 "x":      0,
"y":      0,
"width":    798,
"height":    477,
...
  <g transform="translate(0, 477) scale(1, -1)">
    <g id="gridSVG" fill="rgb(255,255,255)" stroke="rgb(0,0,0)" stroke-dasharray="none" stroke-width="0.75" font-size="16" font-family="Helvetica, Arial, 
....

interactive lineups in SVG format

… example in browser …

interactive lineup

[figures/filec2a75f08a287-multiple.svg]

lineup <- function(method, dframe, filename, script, toggle="toggle") {
  z = as.list(match.call()[-1])

  eval(call(z$method, dframe))
  require(gridSVG)
  grobs <- grid.ls()

  idx <- grep("panel-", grobs$name)
  for (i in idx) { 
    grid.garnish(grobs$name[i],
                 onmouseover=paste("frame('",grobs$name[i+2], ".1')", sep=""),
                 onmouseout=paste("deframe('",grobs$name[i+2], ".1')", sep=""), 
                 onmousedown=paste(sprintf("%shigh(evt, '", toggle),grobs$name[i+2], ".1')", sep=""))
  }

  # use script on server to get locally executable javascript code
  # or use inline option
  grid.script(filename=script)
  gridToSVG(filename)
}

lineup("std_lineup", data, filename= sprintf("%s-multiple.svg", stdname_i_m), toggle="toggle", script="http://www.hofroe.net/examples/lineup/action.js")